﻿using System.CodeDom;

namespace InterfaceWeaver.CustomTool
{
    public class WeavedCodeContext
    {
        public WeavedCodeContext(CodeCompileUnit weavedCode)
        {
            this.WeavedCode = weavedCode;
        }

        /// <summary>
        /// Gets the weaved code.
        /// </summary>
        public CodeCompileUnit WeavedCode { get; private set; }

        /// <summary>
        /// Gets or sets the current namespace declaration.
        /// </summary>
        /// <value>
        /// The current namespace declaration.
        /// </value>
        public CodeNamespace CurrentNamespaceDeclaration { get; private set; }

        /// <summary>
        /// Gets or sets the current type declaration.
        /// </summary>
        public CodeTypeDeclaration CurrentTypeDeclaration { get; private set; }

        /// <summary>
        /// Gets or sets the current code type member declaration.
        /// </summary>
        public CodeMemberPropertyContext CurrentCodeMemberPropertyDeclaration { get; private set; }

        /// <summary>
        /// Gets the current code member event declaration.
        /// </summary>
        public CodeMemberEvent CurrentCodeMemberEventDeclaration { get; private set; }

        /// <summary>
        /// Changes the context.
        /// </summary>
        /// <param name="currentNamespaceDeclaration">The current namespace declaration.</param>
        public void ChangeContext(CodeNamespace currentNamespaceDeclaration)
        {
            WeavedCode.Namespaces.Add(currentNamespaceDeclaration);

            this.CurrentNamespaceDeclaration = currentNamespaceDeclaration;
            this.CurrentTypeDeclaration = null;
            this.CurrentCodeMemberPropertyDeclaration = null;
        }

        /// <summary>
        /// Changes the context.
        /// </summary>
        /// <param name="currentTypeDeclaration">The current type declaration.</param>
        public void ChangeContext(CodeTypeDeclaration currentTypeDeclaration)
        {
            this.CurrentNamespaceDeclaration.Types.Add(currentTypeDeclaration);

            this.CurrentTypeDeclaration = currentTypeDeclaration;
            this.CurrentCodeMemberPropertyDeclaration = null;
        }

        /// <summary>
        /// Changes the context.
        /// </summary>
        /// <param name="currentCodeMemberPropertyDeclaration">The current code member property declaration.</param>
        public void ChangeContext(CodeMemberPropertyContext currentCodeMemberPropertyDeclaration)
        {
            this.CurrentTypeDeclaration.Members.Add(currentCodeMemberPropertyDeclaration.CurrentCodeMemberFieldDeclaration);
            this.CurrentTypeDeclaration.Members.Add(currentCodeMemberPropertyDeclaration.CurrentCodeMemberPropertyDeclaration);
            currentCodeMemberPropertyDeclaration.Hooks.ForEach(hook => this.CurrentTypeDeclaration.Members.Add(hook));

            this.CurrentCodeMemberPropertyDeclaration = currentCodeMemberPropertyDeclaration;
            this.CurrentCodeMemberEventDeclaration = null;
        }

        /// <summary>
        /// Changes the context.
        /// </summary>
        /// <param name="currentEventDeclaration">The current evet declaration.</param>
        public void ChangeContext(CodeMemberEvent currentEventDeclaration)
        {
            this.CurrentTypeDeclaration.Members.Add(currentEventDeclaration);
            this.CurrentCodeMemberEventDeclaration = currentEventDeclaration;
            this.CurrentCodeMemberPropertyDeclaration = null;
        }
    }
}
